<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Compositing</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="cairo, graphics, C, 2D vector library, Compositing">
<meta name="description" content="Compositing">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Compositing</h1>


<p>
In this part of the Cairo graphics programming tutorial, we will 
define compositing operations.
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script>

<p>
<b>Compositing</b> is the combining of visual elements from separate 
sources into single images. They are used to create the illusion that 
all those elements are parts of the same scene. Compositing is videly 
used in film industry to create crowds, entire new worlds which would be expensive or
impossible to create otherwise. (wikipedia.org)
</p>


<h2>Operations</h2>

<p>
There are several compositing operations. The Cairo graphics library has 
14 different compositing operations.
</p>

<pre class="code">
#include &lt;cairo.h&gt;
#include &lt;gtk/gtk.h&gt;

void do_drawing(cairo_t *cr, gint x, gint w,
    gint h, cairo_operator_t op)
{
  cairo_t *first_cr, *second_cr;
  cairo_surface_t *first, *second;

  first = cairo_surface_create_similar(cairo_get_target(cr),
      CAIRO_CONTENT_COLOR_ALPHA, w, h);

  second = cairo_surface_create_similar(cairo_get_target(cr),
      CAIRO_CONTENT_COLOR_ALPHA, w, h);

  first_cr = cairo_create(first);
  cairo_set_source_rgb(first_cr, 0, 0, 0.4);
  cairo_rectangle(first_cr, x, 20, 50, 50);
  cairo_fill(first_cr);

  second_cr = cairo_create(second);
  cairo_set_source_rgb(second_cr, 0.5, 0.5, 0);
  cairo_rectangle(second_cr, x+10, 40, 50, 50);
  cairo_fill(second_cr);

  cairo_set_operator(first_cr, op);
  cairo_set_source_surface(first_cr, second, 0, 0);
  cairo_paint(first_cr);

  cairo_set_source_surface(cr, first, 0, 0);
  cairo_paint(cr);

  cairo_surface_destroy(first);
  cairo_surface_destroy(second);

  cairo_destroy(first_cr);
  cairo_destroy(second_cr);

}

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, 
    gpointer user_data)
{      
  cr = gdk_cairo_create(gtk_widget_get_window(widget));    

  cairo_operator_t oper[] = {
    CAIRO_OPERATOR_DEST_OVER, 
    CAIRO_OPERATOR_DEST_IN, 
    CAIRO_OPERATOR_OUT,
    CAIRO_OPERATOR_ADD, 
    CAIRO_OPERATOR_ATOP,
    CAIRO_OPERATOR_DEST_ATOP,
  };
  
  GtkWidget *win = gtk_widget_get_toplevel(widget);
  
  gint width, height;
  gtk_window_get_size(GTK_WINDOW(win), &amp;width, &amp;height);

  gint i;
  gint x, y;
  for(x=20, y=20, i=0; i &lt; 6; x+=80, i++) {
      do_drawing(cr, x, width, height, oper[i] );
  }

  cairo_destroy(cr);

  return FALSE;
}


int main(int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *darea;  

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  darea = gtk_drawing_area_new();
  gtk_container_add(GTK_CONTAINER (window), darea);

  g_signal_connect(G_OBJECT(darea), "draw", 
      G_CALLBACK(on_draw_event), NULL);  
  g_signal_connect(window, "destroy",
      G_CALLBACK(gtk_main_quit), NULL);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 510, 120);
  gtk_window_set_title(GTK_WINDOW(window), "Compositing operations");

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
In our example, we will show 6 different compositing operations on two squares.
</p>

<pre class="explanation">
first = cairo_surface_create_similar(cairo_get_target(cr),
    CAIRO_CONTENT_COLOR_ALPHA, w, h);

second = cairo_surface_create_similar(cairo_get_target(cr),
    CAIRO_CONTENT_COLOR_ALPHA, w, h);
</pre>

<p>
We create two surfaces.
</p>

<pre class="explanation">
first_cr = cairo_create(first);
cairo_set_source_rgb(first_cr, 0, 0, 0.4);
cairo_rectangle(first_cr, x, 20, 50, 50);
cairo_fill(first_cr);
</pre>

<p>
We draw a rectangle into the surface.
</p>

<pre class="explanation">
cairo_set_operator(first_cr, op);
cairo_set_source_surface(first_cr, second, 0, 0);
cairo_paint(first_cr);
</pre>

<p>
We apply the compositing operation on the surfaces.
</p>


<pre class="explanation">
cairo_set_source_surface(cr, first, 0, 0);
cairo_paint(cr);
</pre>

<p>
Finally we draw the outcome onto the GTK+ window.
</p>

<pre class="explanation">
cairo_operator_t oper[] = {
  CAIRO_OPERATOR_DEST_OVER, 
  CAIRO_OPERATOR_DEST_IN, 
  CAIRO_OPERATOR_OUT,
  CAIRO_OPERATOR_ADD, 
  CAIRO_OPERATOR_ATOP,
  CAIRO_OPERATOR_DEST_ATOP,
};
</pre>

<p>
In our example, we use these six compositing operations.
</p>

<img src="/img/gfx/cairoc/compositing.png" alt="Compositing operations">
<div class="figure">Figure: Compositing operations</div>

<p>
This chapter covered Cairo compositing. 
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified December 13, 2012 <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
